package com.shiro.demo3.config;

import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.realm.Realm;
import org.apache.shiro.session.mgt.SessionManager;
import org.apache.shiro.session.mgt.eis.SessionDAO;
import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.apache.shiro.web.session.mgt.DefaultWebSessionManager;
import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.LinkedHashMap;
import java.util.Map;

@Configuration
public class ShiroAuthConfig {
    // ShiroFilter
    @Bean
    public ShiroFilterFactoryBean shiroFilter(/*@Qualifier("securityManager") SecurityManager securityManager*/){
        ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
        shiroFilterFactoryBean.setSecurityManager(securityManager());
        shiroFilterFactoryBean.setLoginUrl("/page/login");
        // 没有权限默认跳转的页面，登录的用户访问了没有被授权的资源自动跳转到的页面。
        shiroFilterFactoryBean.setUnauthorizedUrl("/user/test2");

        // 控制,访问xx/xx资源,需要xx权限
        Map<String, String> map = new LinkedHashMap<>();
        // anon表示,不需要(登录)认证,就能直接访问
        map.put("/page/login","anon");
        map.put("/page/loginData","anon");
        map.put("/user/test","authc");
        shiroFilterFactoryBean.setFilterChainDefinitionMap(map);

        return shiroFilterFactoryBean;
    }

    // 安全管理器
    @Bean
    public SecurityManager securityManager(){
        DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
        securityManager.setRealm(realm());
        securityManager.setSessionManager(sessionManager());
        return securityManager;
    }

    // Realm
    @Bean
    public Realm realm(){
        MyRealm myRealm = new MyRealm();
        // 配置加密方式
        HashedCredentialsMatcher credentialsMatcher = new HashedCredentialsMatcher();
        credentialsMatcher.setHashAlgorithmName("md5");
        // 加密迭代次数,md5加密次数
         credentialsMatcher.setHashIterations(1024);
        myRealm.setCredentialsMatcher(credentialsMatcher);
        return myRealm;
    }
    /**
     * 下面两个方法是开启支持注解配置权限的
     */
    @Bean
    public DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator(){
        DefaultAdvisorAutoProxyCreator proxyCreator = new DefaultAdvisorAutoProxyCreator();
        proxyCreator.setProxyTargetClass(true);
        return proxyCreator;
    }
    @Bean
    public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(SecurityManager securityManager){
        AuthorizationAttributeSourceAdvisor sourceAdvisor = new AuthorizationAttributeSourceAdvisor();
        sourceAdvisor.setSecurityManager(securityManager);
        return sourceAdvisor;
    }
    /**
     * 配置Redis会话管理器
     */
    @Bean
    public SessionManager sessionManager(){
        DefaultWebSessionManager sessionManager = new DefaultWebSessionManager();
        sessionManager.setSessionDAO(redisSessionDAO());
        // 设置会话过期时间
        sessionManager.setGlobalSessionTimeout(3*60*1000);  // 默认半小时
        sessionManager.setDeleteInvalidSessions(true);
        // 设置会话定时检查
        sessionManager.setSessionValidationInterval(180000);    // 默认一小时
        sessionManager.setSessionValidationSchedulerEnabled(true);
        return sessionManager;
    }
    @Bean
    public SessionDAO redisSessionDAO(){
        // 这里需要实例化自定义的SessionDAO
        ShiroRedisSessionDao sessionDao = new ShiroRedisSessionDao();
        return sessionDao;
    }
}
